package org.biloxi.game.gamerules;

import org.biloxi.commands.Command;
import org.biloxi.commands.CommandRepository;
import org.biloxi.commands.Filter;
import org.biloxi.commands.Listener;
import org.biloxi.commands.changephase.ChangePhase;
import org.biloxi.commands.changephase.ChangePhase.Options;
import org.biloxi.commands.changephase.ChangePhase.Result;
import org.biloxi.model.GameState;
import org.biloxi.model.GameState.Phase;

/**
 * This GameRule is responsible for advancing the Games Phase when a Phase has been been complete 
 * (game has changed to an "after" Phase).
 * 
 * NextPhaseRules listens when the {@link ChangePhase} command has been executed to move to an 
 * "after" Phase.  At that point call {@link ChangePhase} to move to the next appropriate Phase.  
 * 
 * @author Peter.WM.Wong@gmail.com
 *
 */
public class NextPhaseRules extends GameRule implements Listener<ChangePhase.Options, ChangePhase.Result> {

	/**
	 * Attaches rule by registering a listener to {@link ChangePhase} command for "after" or {@link Phase#BOT} phase change.
	 * @param cmd 
	 */
	public NextPhaseRules(CommandRepository cmd) {
		super(cmd);
		
		_c.changePhase().do_(this,
			new Filter<Result>(){
				public boolean allow(Result r) {
					return (r.phase.toString().contains("After") ||
							r.phase == Phase.BOT);	// Is an "after" or BOT phase
				}
			}
		);
		
	}
 
	/**
	 * Advances the game by changing the phase to the next phase.
	 * If the player has lost already, no phase change occurs and should result to returning into the Game loop.   
	 */
	public void handle(Command<Options, Result> cmd, Options options, Result result, GameState g) {
		
		// As long as the player hasn't already lost the game.
		if(!g.getTurnsPlayerState().hasLost()){
			
			// Shouldn't null out, as we have already filtered Command for Phases in our map.
			_c.changePhase( new ChangePhase.Options(Phase.getNextPhase(result.phase)) );  
		}
	}

}
